package org.codersunit.radboid.data;

import java.util.Calendar;
import java.util.Comparator;
import java.util.TreeSet;
import org.codersunit.radboid.util.Tuple;

public class Schedule extends TreeSet<Schedule.Period> {
	private static final long serialVersionUID = 944217743796757345L;
	
	public static final int DAILY = 0;
	public static final int WEEKLY = 1;
	public static final int MONTHLY = 2;
	public static final int YEARLY = 4;
	
	private final int period;
	private final DateComparator dateComparator;

	public Schedule() {
		this(DAILY);
	}
	
	public Schedule(int period) {
		super(new PeriodComparator(period));
		this.period = period;
		dateComparator = new DateComparator(period);
	}
	
	public int getPeriod() {
		return period;
	}
	
	public Period add(final Calendar start) {
		final Period period = new Period(start, new LectureList());
		add(period);
		return period;
	}
	
	public Period add(final Lecture lecture) {
		Calendar start = lecture.getStart();
		for(Period p : this) {
			int diff = dateComparator.compare(p.getDate(), start);
			if(diff == 0) {
				p.getLectures().add(lecture);
				return p;
			} else if(diff > 0) {
				break;
			}
		}
		Period newPeriod = add(start);
		newPeriod.getLectures().add(lecture);
		return newPeriod;
	}
	
	public Object getFlat(int position) {
		for(final Period p : this) {
			if(position == 0) {
				return p.getDate();
			} else if(position < p.getLectures().size()) {
				return p.getLectures().get(position);
			} else {
				position -= p.getLectures().size();
			}
		}
		return null;
	}
	
	public Tuple<Period, Integer> getLocation(int position) {
		for(Period p : this) {
			if(position <= p.getLectures().size()) {
				return new Tuple<Period, Integer>(p, position - 1);
			} else {
				position -= p.getLectures().size();
			}
		}
		return null;
	}
	
	public int getFlatCount() {
		int count = 0;
		for(Period p : this) {
			count += p.getLectures().size() + 1;
		}
		return count;
	}
	
	public int getLectureCount() {
		int count = 0;
		for(Period p : this) {
			count += p.getLectures().size();
		}
		return count;
	}
	
	public int getPeriodCount() {
		return size();
	}
	
	public static class Period {
		private final Calendar s;
		private final LectureList l;
		
		public Period(final Calendar start, final LectureList lectures) {
			s = start;
			l = lectures;
		}
		
		public Calendar getDate() {
			return s;
		}
		
		public LectureList getLectures() {
			return l;
		}
	}
	
	public static class PeriodComparator implements Comparator<Period> {
		private DateComparator dateCmp;
		public PeriodComparator(int period) {
			dateCmp = new DateComparator(period);
		}
		
		@Override
		public int compare(Period f, Period s) {
			return dateCmp.compare(f.getDate(), s.getDate());
		}
		
		public DateComparator getDateComparator() {
			return dateCmp;
		}
	}
}
